package org.btik.light.mobile.server;

import org.btik.context.thread.SystemControlAble;

import java.io.Serializable;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author lustre
 * @since 2023/9/17 16:37
 */
public class TimeOutCache extends Thread implements SystemControlAble {

    private volatile boolean runFlag = true;

    private final byte[] lock = new byte[0];

    private long interval = 5 * 60 * 1000;

    public void setInterval(long interval) {
        this.interval = interval;
    }

    private final ConcurrentHashMap<String, ConcurrentHashMap<Serializable, TimeoutBean<?>>> timeoutCache = new ConcurrentHashMap<>();

    public <T> T getObj(String namespace, Serializable key) {
        ConcurrentHashMap<Serializable, TimeoutBean<?>> subMap = timeoutCache.get(namespace);
        if (null == subMap) {
            return null;
        }
        TimeoutBean<?> timeoutBean = subMap.get(key);
        if(timeoutBean == null){
            return null;
        }
        return (T) timeoutBean.tagert();
    }

    public void removeObj(String namespace, Serializable key) {
        ConcurrentHashMap<Serializable, TimeoutBean<?>> subMap = timeoutCache.get(namespace);
        if (null == subMap) {
            return;
        }
        subMap.remove(key);
    }

    public <T> void save(String namespace, Serializable key, T tagert, long timeout) {
        timeoutCache.computeIfAbsent(namespace, (k) -> new ConcurrentHashMap<>()).put(key, new TimeoutBean<>(tagert, System.currentTimeMillis(), timeout));
    }

    @Override
    public void run() {
        while (runFlag) {
            synchronized (lock) {
                try {
                    lock.wait(interval);
                } catch (InterruptedException e) {
                    if (!runFlag) {
                        break;
                    }
                }
            }
            long now = System.currentTimeMillis();
            for (Map.Entry<String, ConcurrentHashMap<Serializable, TimeoutBean<?>>> entry : timeoutCache.entrySet()) {
                ConcurrentHashMap<Serializable, TimeoutBean<?>> subMap = entry.getValue();
                subMap.forEach((key, bean) -> {
                    long time = bean.lastActiveTime();
                    if ((time - now) > bean.timeout()) {
                        subMap.remove(key);
                    }
                });
            }

        }
    }


    @Override
    public void shutdown(String msg) {
        runFlag = false;
    }
}
